// shallowReactive（浅的劫持，浅的监视，浅的响应数据）与 reactive（深的）
// 定义一个reactiveHandler处理对象
const reactiveHandler = {
    // 获取属性值
    get(target, prop) {
        if (prop === '_is_reactive') return true
        const res = Reflect.get(target, prop);
        console.log('拦截了读取数据', prop, res);
        return res;
    },
    // 修改添加属性
    set(target, prop, value) {
        const res = Reflect.set(target, prop, value);
        console.log('拦截了修改添加数据', prop, value);
        return res;
    },
    // 删除某个属性
    deleteProperty(target, prop) {
        const res = Reflect.deleteProperty(target, prop);
        console.log('拦截了删除数据', prop);
        return res;
    }
}
// 定义一个shallowReactive函数，传入一个目标对象
function shallowReactive(target) {
    // 判断当前的目标对象是不是obj类型（对象/数据）
    if (target && typeof target === 'object') {
        return new Proxy(target, reactiveHandler)
    }
    // 如果传入的数据是基本类型的数据，那么就直接返回
    return target
}

// 定义一个reactive函数，传入一个目标对象
function reactive(target) {
    // 对数组或者对象中所有数据进行reactive递归处理
    // 判断当前的目标对象是不是对象类型
    if (target && typeof target === 'object') {
        // 判断当前的目标对象是不是数组类型
        if (Array.isArray(target)) {
            target.forEach((item, index) => {
                target[index] = reactive(item)
            })
        } else {
            // 判断当前的目标对象是不是对象类型
            Object.keys(target).forEach(key => {
                target[key] = reactive(target[key])
            })
        }
        return new Proxy(target, reactiveHandler)
    }
    // 如果传入的数据是基本类型的数据，那么就直接返回
    return target
}

// =============================================================
// 定义了一个readonlyHandler处理器
const readonlyHandler = {
    // 获取属性值
    get(target, prop) {
        if (prop === '_is_readonly') return true
        const res = Reflect.get(target, prop);
        console.log('拦截了读取数据', prop, res);
        return res;
    },
    // 修改添加属性
    set(target, prop, value) {
        console.warn('只能读取数据,不能修改或添加数据')
        return true;
    },
    // 删除某个属性
    deleteProperty(target, prop) {
        console.warn('只能读取数据,不能删除数据')
        return true;
    }
}

// 定义一个shallowReadonly函数
function shallowReadonly(target) {
    // 需要判断当前的数据是不是对象
    // 判断当前的目标对象是不是obj类型（对象/数据）
    if (target && typeof target === 'object') {
        return new Proxy(target, readonlyHandler)
    }
    return target
}

// 定义一个readonly函数
function readonly(target) {
    // 对数组或者对象中所有数据进行reactive递归处理
    // 判断当前的目标对象是不是对象类型
    if (target && typeof target === 'object') {
        // 判断当前的目标对象是不是数组类型
        if (Array.isArray(target)) {
            target.forEach((item, index) => {
                target[index] = readonly(item)
            })
        } else {
            // 判断当前的目标对象是不是对象类型
            Object.keys(target).forEach(key => {
                target[key] = readonly(target[key])
            })
        }
        return new Proxy(target, readonlyHandler)
    }
    // 如果传入的数据是基本类型的数据，那么就直接返回
    return target
}


// ============================
// 定义一个shallowRef函数
function shallowRef(target) {
    return {
        // 保存target 数据保存起来
        _value: target,
        get value() {
            console.log("劫持到了读取数据")
            return this._value
        },
        set value(val) {
            console.log("劫持到了设置数据, 准备更新界面", val)
            this._value = val
        }
    }
}

// 定义一个ref函数
function ref(target) {
    target = reactive(target)
    return {
        // 保存target 数据保存起来
        _is_ref: true, // 标识当前的对象是ref对象
        // 保存target数据保存起来
        _value: target,
        get value() {
            console.log("劫持到了读取数据")
            return this._value
        },
        set value(val) {
            console.log("劫持到了设置数据, 准备更新界面", val)
            this._value = val
        }
    }
}


// 定义一个函数isRef，判断当前的对象是不是ref对象
function isRef(obj) {
    return obj && obj._is_ref
}
// 定义一个函数isReactive，判断当前的对象是不是reactive对象
function isReactive(obj) {
    return obj && obj._is_reactive
}
// 定义一个函数isReadonly，判断当前的对象是不是readonly对象
function isReadonly(obj) {
    return obj && obj._is_readonly
}
// 定义一个函数isProxy，判断当前的对象是不是reactive或者readonly对象
function isProxy(obj) {
    return isReactive(obj) || isReadonly(obj);
}